package cn.maihe.elg.operation.centers.fuzhou.config;

import cn.maihe.elg.operation.centers.fuzhou.auth.FZAuthorization;
import cn.maihe.elg.operation.centers.fuzhou.auth.FZCenterAuthConfig;
import cn.maihe.elg.operation.centers.fuzhou.auth.FZEncryption;
import cn.maihe.elg.operation.config.ElgAuthConfig;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.ValidateUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description 海迈中心配置文件
 * @Author WJH
 * @Date 2022/03/07
 */
@Configuration
@ConfigurationProperties(prefix = "cn.maihe.elg.center-info-config.hymake")
@Getter
@Setter
@Slf4j
public class FZMakeInfoConfig {
    /**
     * key=CenterNoEnum.name.toLowerCase yml自动加载
     */
    private Map<String, CenterInfo> hymakeCenterMap = new HashMap<>();

    @JsonIgnore
    private final static Map<String, FZCenterAuthConfig> authConfigMap = new HashMap<>();

    @Resource
    private ElgAuthConfig elgAuthConfig;

    private CenterNoEnum getByCenterNoEnum(String centerNoEnumName) {
        CenterNoEnum centerNoEnum = Arrays.stream(CenterNoEnum.values()).filter(o -> o.name().toLowerCase().equalsIgnoreCase(centerNoEnumName)).findFirst().orElse(null);
        Assert.notNull(centerNoEnum, "非法中心枚举名称[" + centerNoEnumName + "]");
        return centerNoEnum;
    }

    @PostConstruct
    public void init() {
        if (hymakeCenterMap != null && hymakeCenterMap.size() != 0) {
            hymakeCenterMap.entrySet().forEach(entry -> {
                CenterNoEnum centerNoEnum = getByCenterNoEnum(entry.getKey());
                FZCenterAuthConfig authConfig = getAuthConfig(centerNoEnum);
                log.info("初始化加载[{}]中心配置参数成功", centerNoEnum);
                ElgLogger.debug(log, l -> l.debug("初始化加载[{}]中心配置参数:{}", centerNoEnum, JSON.toJSONString(authConfig)));
            });
        }
    }

    private CenterInfo getCenterInfo(CenterNoEnum centerNoEnum) {
        CenterInfo centerInfo = hymakeCenterMap.get(centerNoEnum.name().toLowerCase());
        Assert.notNull(centerInfo, () -> centerNoEnum + "未配置");
        try {
            ValidateUtil.validate(centerInfo);
        } catch (Exception e) {
            throw new RuntimeException("中心[" + centerNoEnum + "]配置信息错误");
        }

        return centerInfo;
    }

    /**
     * 根据新点各中心获取其配置信息
     *
     * @param centerNoEnum
     * @return
     */
    @JsonIgnore
    public FZCenterAuthConfig getAuthConfig(CenterNoEnum centerNoEnum) {
        FZCenterAuthConfig centerAuthConfig = authConfigMap.get(centerNoEnum.getCenterNo());
        if (centerAuthConfig == null) {
            CenterInfo centerInfo = this.getCenterInfo(centerNoEnum);
            FZAuthorization authorization = new FZAuthorization(elgAuthConfig, centerInfo);
            FZEncryption encryption = new FZEncryption(elgAuthConfig, centerInfo);

            centerAuthConfig = new FZCenterAuthConfig(authorization, encryption, centerInfo);
            authConfigMap.put(centerNoEnum.getCenterNo(), centerAuthConfig);
        }

        return centerAuthConfig;
    }

    @Data
    public static class CenterInfo implements Serializable {
        /**
         * appId 中心提供 签名时用到
         */
        @NotEmpty(message = "appId不能为空")
        private String appId;
        /**
         * version 中心提供 签名时用到
         */
        @NotEmpty(message = "版本不能为空")
        private String version;
        /**
         * 盐 签名时用到
         */
        @NotEmpty(message = "slat不能为空")
        private String slat;

        /**
         * sm2私钥，解密时用到，值为16进制字符串
         * fuzhou复用非sm2 金融机构各自的RSA私钥[RSA私钥：rsa_sk]
         */
        @NotEmpty(message = "sm2PriKey不能为空")
        private String sm2PriKey;
        /**
         * sm2公钥，加密时用到，值为16进制字符串
         * fuzhou复用非sm2 金融机构各自的RSA公钥[RSA公钥：rsa_pk]
         */
        @NotEmpty(message = "sm2PubKey不能为空")
        private String sm2PubKey;

        /**
         * 交易系统电子保函服务公用RSA公钥[api_rsa_pk]
         */
//        @NotEmpty(message = "交易系统电子保函服务公用RSA公钥不能为空")
        private String apiRsaPk;

        /**
         * 系统名称
         */
        @NotEmpty(message = "中心系统名称不能为空")
        private String sysName;


        /**
         * 保费费率百分几例如0.15即为0.15%
         */
        @NotEmpty(message = "保费费率不能为空")
        private String feeRate;
        /**
         * 保费保底金额：单位元
         */
        @NotNull(message = "保费保底金额不能为空")
        private Long minFeeYuan;


        /**
         * 请求平台接口地址前缀：不包含接口名称的
         */
        @NotEmpty(message = "中心url不能为空")
        private String url;

        /**
         * 支付结果通知完整地址：
         */
        private String payResultReceiveUrl;
        /**
         * 保函地址接收完整地址：
         */
        private String bondDownLoadUrl;
        /**
         * 保函撤销结果接收完整地址：
         */
        private String guaranteeBackNoticeUrl;
        /**
         * 理赔结果接收完整地址：
         */
        private String claimResultReceiveUrl;
        /**
         * 同步支付结果至中心 0否，其他都是默认是
         */
        private String syncPayResult;

        /**
         * 福州资源中心,颁发给金融机构的api_key
         */
        private String apiKey;

        /**
         * 福州资源中心,颁发给金融机构的api_secret
         */
        private String apiSecret;

        /**
         * 福州资源中心,接口地址
         */
        private String apiUrl;

        /**
         * 对接金融机构id
         */
        private String btcId;
    }

}
